﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace Lm.Common.ExtensionMethods
{
    public static class ModelExt
    {
        /// <summary>
        /// Model转换成Row
        /// </summary>
        /// <param name="model"></param>
        /// <param name="row"></param>
        /// <param name="treat">Model与Row互相转换时，如果结构不相同时的处理方式</param>
        /// <returns></returns>

        public static DataRow ToRow(this  IModel model, DataRow row, SchemaNotSame treat)
        {
            List<string> propertyNameList = null;
            if (model.SchemaSameWith(row))
            { propertyNameList = model.GetPropertyList(); }
            else
            {
                switch (treat)
                {
                    case SchemaNotSame.ThrowException:
                        {
                            throw new Exception("Model和Row的结构不同");
                        }
                    case SchemaNotSame.UseSource:
                        {
                            propertyNameList = model.GetPropertyList();
                            break;
                        }
                    case SchemaNotSame.UseTarget:
                        {
                            propertyNameList = row.GetColumnsList();
                            break;
                        }
                }
            }
            foreach (var p in propertyNameList)
            {
                var value = model.GetType().GetProperty(p).GetValue(model, null);
                if (value == null)
                { row[p] = DBNull.Value; }
                else
                { row[p] = value; }
            }
            return row;
        }

        /// <summary>
        /// 得到包含对象所有属性的字符串列表
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static List<string> GetPropertyList(this IModel model)
        {
            return model.GetType().GetProperties().Select(t => t.Name).ToList();
        }

        /// <summary>
        /// model和row的结构是否相同
        /// </summary>
        /// <param name="model"></param>
        /// <param name="row"></param>
        /// <returns></returns>
        public static bool SchemaSameWith(this  IModel model, DataRow row)
        {
            var columnsList = row.GetColumnsList();
            var propertyList = model.GetPropertyList();
            if (columnsList.SameWith(propertyList) == false)
            { return false; }
            foreach (var c in columnsList)
            {
                var pType = model.GetType().GetProperty(c).PropertyType;
                if (pType.IsGenericType && pType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    if (row.Table.Columns[c].DataType != pType.GetGenericArguments().First())
                    { return false; }
                }
                else
                {
                    if (row.Table.Columns[c].DataType != model.GetType().GetProperty(c).PropertyType)
                    { return false; }
                }
            }
            return true;
        }

        /// <summary>
        /// 比较两个model所有属性的值是否相同
        /// </summary>
        /// <param name="model1"></param>
        /// <param name="model2"></param>
        /// <returns></returns>
        public static bool SameWith(this IModel model1, IModel model2)
        {
            if(model1.GetType()!=model2.GetType())
            { return false; }
            foreach (var p in model1.GetPropertyList())
            {
                var property = model1.GetType().GetProperty(p);
                var v1 = property.GetValue(model1, null);
                var v2 = property.GetValue(model2, null);
                //两个都为null
                if (v1 == null && v2 == null)
                { continue; }
                //一个为null
                if (v1 == null || v2 == null)
                { return false; }
                //都不为null            
                if (v1.ToString() != v2.ToString())
                { return false; } 
            }
            return true;
        }

        /// <summary>
        /// 复制一个model
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static T Copy<T>(this T model) where T : IModel, new()
        {
            var result = new T();
            foreach (var p in model.GetPropertyList())
            {
                result.GetType().GetProperty(p).SetValue(result,
                    model.GetType().GetProperty(p).GetValue(model, null), null);
            }
            return result;
        }

        public static string ToXml(this IModel model)
        {
            return new Xml.XmlSerializer().Serialize(model);
        }

        public static void TrimStringProperty(this IModel model)
        {
            var properties = model.GetType().GetProperties();
            foreach (var p in properties)
            {
                if (p.PropertyType == typeof(string) && p.GetValue(model, null) != null)
                {
                    p.SetValue(model, p.GetValue(model, null).ToString().Trim(), null);
                }
            }
        }

    }
}
